#pragma once
#include <memory>
#include <string>
#include <vector>
#include <atomic>
#include <random>
#include <functional>
#include <mutex>
#include <unordered_set>
#include <map>
#include "media.h"
//#include "RTPConnection.h"

namespace jlh
{
	class MediaSource;
	class RTPConnection;

	class MediaSession
	{
	public:
		typedef std::function<void(MediaSessionId sessionId, uint32_t numClients)> NotifyCallback;

		static MediaSession* CreateNew(std::string url_suffix = "live");
		virtual ~MediaSession();

		void SetNotifyCallback(const NotifyCallback& cb) { notify_callback_ = cb; }

		void SetRtspUrlSuffix(std::string& suffix) { suffix_ = suffix; }
		std::string GetRtspUrlSuffix() const { return suffix_; }
		
		MediaSessionId GetMediaSessionId() { return session_id_; }

		bool AddSource(MediaChannelId channel_id, MediaSource* source);
		bool RemoveSource(MediaChannelId channel_id);

		bool AddClient(uint32_t fd, std::shared_ptr<RTPConnection> rtp_conn);
		void RemoveClient(uint32_t rtspfd);

		MediaSource* GetMediaSource(MediaChannelId channelId);
		std::string GetSdpMessage(std::string sessionName);

		bool HandleFrame(MediaChannelId channel_id, AVFrame frame);

		bool IsMulticast() const {
			return is_multicast_;
		}

		uint32_t GetNumClient() const {
			return clients_.size();
		}

	private:
		MediaSession(const std::string& url_suffix);

		MediaSessionId session_id_ = 0;
		std::string suffix_;
		std::string sdp_;

		std::vector<std::unique_ptr<MediaSource>> media_sources_;
		//

		NotifyCallback notify_callback_ = nullptr;
		std::mutex mutex_;
		std::mutex map_mutex_;
		std::map<uint32_t, std::weak_ptr<RTPConnection>> clients_;

		bool is_multicast_ = false;
		uint16_t multicast_port_[MAX_MEDIA_CHANNEL];
		std::string multicat_ip_;
		std::atomic_bool has_new_client_ = false;

		static std::atomic_uint last_session_id_;
	};

	typedef std::shared_ptr<MediaSession> MediaSessionPtr;

}


